package com.huli.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huli.dao.OPropertyCompanyDeductMapper;
import com.huli.dao.OrdersMapper;
import com.huli.dao.TransactionMapper;
import com.huli.domain.*;
import com.huli.exception.CustomException;
import com.huli.feign.*;
import com.huli.param.OrdersByOwnerParam;
import com.huli.param.OrdersByUserParam;
import com.huli.param.OrdersCreateParam;
import com.huli.param.OwnerParam;
import com.huli.service.OrdersService;
import com.huli.utils.Result;
import com.huli.utils.TimeUtils;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class OrdersServiceImpl implements OrdersService {

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    CarportFeign carportFeign;

    @Autowired
    UserClient userClient;

    @Autowired
    CouponClient couponClient;

    @Autowired
    MemberClient memberClient;

    @Autowired
    OwnerFeign ownerFeign;

    @Autowired
    TransactionMapper transactionMapper;

    @Autowired
    OPropertyCompanyDeductMapper oPropertyCompanyDeductMapper;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    @Override
    public BigDecimal howMuch(OrdersCreateParam param) {
        //得到carport
        Result carportResult = carportFeign.selectCarportById(param.getCarportId());
        Carport carport = Result.getOriginal(carportResult, Carport.class);
        //计算时间差并生成原价
        long min = TimeUtils.getMinuteSub(param.getStartTime(), param.getEndTime());
        BigDecimal originPrice = carport.getCarportPrice().multiply(new BigDecimal(min / 60.00));
        //得到用户
        Result userResult = userClient.getUserByCarId(param.getCarId());
        User user = Result.getOriginal(userResult, User.class);
        //计算真实价格
        BigDecimal realPrice = new BigDecimal("0.00");
        // - 优惠券
        if (param.getCouponId() != 0) {
            Result couponR = couponClient.getCoupon(param.getCouponId());
            Coupon coupon = Result.getOriginal(couponR, Coupon.class);
            realPrice = originPrice.multiply(coupon.getCouponDiscount());
        }
        // - 会员
        if (user.getUserVipId() != 0) {
            Result result = memberClient.selectUserVipById(user.getUserVipId());
            UserVip userVip = Result.getOriginal(result, UserVip.class);
            realPrice = originPrice.multiply(userVip.getUserVipDiscount());
        }
        return realPrice;
    }

    @Override
    @Transactional
    public void newOrders(OrdersCreateParam param) {
        BigDecimal price = howMuch(param);
        Orders orders = Orders.builder().carId(param.getCarId())
                .carportId(param.getCarportId())
                .couponId(param.getCouponId())
                .ordersEndTime(param.getEndTime())
                .ordersMoney(price)
                .ordersStartTime(param.getStartTime())
                .ordersStatus(0)
                .build();
        ordersMapper.insert(orders);
        //设置redis15分钟的键
        redisTemplate.opsForValue().set("orders:timeout:" + orders.getOrdersId(), "0", 15, TimeUnit.MINUTES);
        //发送消息 设置延时时间14级 对应10分钟
        Message message = new Message();
        //TODO
        message.setDelayTimeLevel(14);
        message.setTopic("ordersTime");
        try {
            //消息内容为redis的键 延时10分钟后如果还是查询到该键 说明未支付 订单取消
            message.setBody(("orders:timeout:" + orders.getOrdersId()).getBytes("UTF-8"));
            DefaultMQProducer defaultMQProducer = new DefaultMQProducer();
            defaultMQProducer.setNamesrvAddr("49.234.234.211:9876");
            defaultMQProducer.setProducerGroup("ordersTimeGroup");
            defaultMQProducer.start();
            defaultMQProducer.send(message);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Long getOrdersTimeout(int ordersId) {
        return redisTemplate.opsForValue().getOperations().getExpire("orders:timeout:" + ordersId);
    }

    @Override
    @Transactional
    public void delOrders(int ordersId) {
        //验证订单状态
        int userId = getUserIdByOrdersId(ordersId);
        Result userR = userClient.getUser(userId);
        User user = Result.getOriginal(userR, User.class);
        Long ordersTimeout = getOrdersTimeout(ordersId);
        if (ordersTimeout <= -2) throw new CustomException(Result.failedResult(500, "该订单已支付或不存在"));
        //根据剩余时间扣除用户信誉
        Result result = userClient.changeSource(userId, (int) (user.getUserSource() - (((ordersTimeout - 300) / 600.0) * 100)));
        if (!result.isSuccess()) throw new CustomException(result);
        //删除订单 删除redis键
        ordersMapper.deleteById(ordersId);
        redisTemplate.delete("orders:timeout:" + ordersId);
    }

    @Override
    public List<Orders> getUserOrders(OrdersByUserParam param) {
        return ordersMapper.getByUser(param);
    }

    @Override
    public List<Orders> getOwnerOrders(OrdersByOwnerParam param) {
        return ordersMapper.getByOwner(param);
    }

    @Override
    @Transactional
    public void payOrders(int ordersId) {
        //判断信息是否正常
        Orders orders = getOrders(ordersId);
        if (orders.getOrdersStatus() != 0) throw new CustomException(Result.failedResult(500, ""));
        Result userByCarId = userClient.getUserByCarId(orders.getCarId());
        User user = Result.getOriginal(userByCarId, User.class);
        //判断余额
        if (user.getUserMoney().compareTo(orders.getOrdersMoney()) == -1)
            throw new CustomException(Result.failedResult(300, "用户余额不足"));
        //修改余额
        Result result = userClient.changeMoney(user.getUserId(), user.getUserMoney().subtract(orders.getOrdersMoney()));
        if (!result.isSuccess()) throw new CustomException(result);
        //修改订单状态
        ordersMapper.updateById(orders.setOrdersStatus(1));
        //生成交易记录
        Transaction transaction = Transaction.builder()
                .ordersId(orders.getOrdersId())
                .transactionStatus(0)
                .transactionTime(TimeUtils.now())
                .userId(user.getUserId()).build();
        transactionMapper.insert(transaction);
        //删除redis键
        Boolean delete = redisTemplate.delete("orders:timeout:" + ordersId);
        //if (!delete) throw new CustomException(Result.failedResult(500, "redis异常"));
    }

    @Override
    @Transactional
    public void backOrders(int ordersId) {
        Date now = TimeUtils.now();
        //计算使用时间比例
        Orders orders = getOrders(ordersId);
        long totalMin = TimeUtils.getMinuteSub(orders.getOrdersStartTime(), orders.getOrdersEndTime());
        long spendMin = TimeUtils.getMinuteSub(orders.getOrdersStartTime(), now);
        double spendPart = spendMin / (double) totalMin;
        //如果时间比大于0.5 加信誉 否则减信誉
        int userId = getUserIdByOrdersId(ordersId);
        Result userR = userClient.getUser(userId);
        User user = Result.getOriginal(userR, User.class);
        int userSource = spendPart > 0.5 ?
                user.getUserSource() + ((int) ((spendPart - 0.5) * 100))
                : user.getUserSource() - ((int) ((0.5 - spendPart) * 100));
        Result result = userClient.changeSource(userId, userSource);
        if (!result.isSuccess()) throw new CustomException(result);
        //根据时间比退钱
        BigDecimal payback = orders.getOrdersMoney().subtract(
                orders.getOrdersMoney().multiply(new BigDecimal(spendPart)));
        Result result1 = userClient.changeMoney(user.getUserId(), user.getUserMoney().subtract(payback));
        if (!result1.isSuccess()) throw new CustomException(result1);
        //改变订单状态与结束时间
        ordersMapper.updateById(orders.setOrdersEndTime(now).setOrdersStatus(-1));
        //生成交易记录
        Transaction transaction = Transaction.builder()
                .userId(userId)
                .transactionTime(now)
                .transactionStatus(1)
                .ordersId(ordersId).build();
        transactionMapper.insert(transaction);
        System.out.println(11111);
        //发钱
        BigDecimal profit = orders.getOrdersMoney().subtract(payback);
        Result result2 = carportFeign.selectCarportById(orders.getCarportId());
        Carport carport = Result.getOriginal(result2, Carport.class);
        Result result3 = carportFeign.selectGarage(carport.getCarportId());
        Garage garage = Result.getOriginal(result3, Garage.class);
        System.err.println(carport);
        System.err.println(garage);
        postMoney(profit, garage.getPropertyCompanyId(), carport.getOwnerId());
    }

    @Override
    @Transactional
    public void finishOrders(int ordersId) {
        Orders orders = getOrders(ordersId);
        //加积分
        int userId = getUserIdByOrdersId(ordersId);
        Result userR = userClient.getUser(userId);
        User user = Result.getOriginal(userR, User.class);
        Result result = userClient.changeSource(user.getUserId(), user.getUserSource() + 100);
        if (!result.isSuccess()) throw new CustomException(result);
        //生成交易记录
        Transaction transaction = Transaction.builder()
                .userId(userId)
                .transactionTime(TimeUtils.now())
                .transactionStatus(2)
                .ordersId(ordersId).build();
        transactionMapper.insert(transaction);
        //发钱
        Result result2 = carportFeign.selectCarportById(orders.getCarportId());
        Carport carport = Result.getOriginal(result2, Carport.class);
        Result result3 = carportFeign.selectGarage(carport.getCarportId());
        Garage garage = Result.getOriginal(result3, Garage.class);
        postMoney(orders.getOrdersMoney(), garage.getPropertyCompanyId(), carport.getOwnerId());
        //TODO 优惠券
    }

    @Override
    public List<Orders> getByGarage(int garageId) {
        List<Orders> byGarage = ordersMapper.getByGarage(garageId);
        if (byGarage == null || byGarage.size() == 0) throw new CustomException(Result.failedResult(300, "当前车库无订单信息"));
        return byGarage;
    }

    @Override
    public Orders getOrders(int ordersId) {
        Orders orders = ordersMapper.selectById(ordersId);
        if (orders == null) throw new CustomException(Result.failedResult(500, "订单不存在"));
        return orders;
    }

    @Override
    public List<Orders> getByCarportId(int carportId) {
        List<Orders> carports = ordersMapper.selectList(new QueryWrapper<Orders>()
                .eq("carport_id", carportId).eq("orders_status", 1));
        if (carports == null || carports.size() == 0) throw new CustomException(
                Result.failedResult(300, "车位无预定或在使用户订单"));
        return carports;
    }

    @Override
    public int getUserIdByOrdersId(int ordersId) {
        return ordersMapper.getUserIdByOrdersId(ordersId);
    }

    @Override
    @Transactional
    public void postMoney(BigDecimal money, int propertyId, int ownerId) {
        //查询得到比例
        PropertyCompanyDeduct propertyCompanyDeduct =
                oPropertyCompanyDeductMapper.selectOne(new QueryWrapper<PropertyCompanyDeduct>().eq("property_company_id", propertyId));
        BigDecimal propertyDiscount = propertyCompanyDeduct.getPropertyCompanyDeductDiscount();
        //按比例发钱给用户
        Result result = ownerFeign.selectOwnerById(OwnerParam.builder().ownerId(ownerId).build());
        Owner owner = Result.getOriginal(result, Owner.class);
        BigDecimal ownerMoney = owner.getOwnerMoney()
                .multiply(new BigDecimal("0.90").subtract(propertyDiscount).multiply(money));
        Result result1 = ownerFeign.updateOwnerMoney(OwnerParam.builder().ownerId(ownerId).ownerMoney(ownerMoney).build());
        if (!result1.isSuccess()) throw new CustomException(result1);
        //todo 物业怎么收钱
    }
}
